package com.ams.handler.baiy;

import com.alibaba.fastjson.JSONObject;
import com.ams.common.entity.DataInsEntity;
import com.ams.common.entity.InsDetailEntity;
import com.ams.common.entity.InsEntity;
import com.ams.common.utils.RedisKeys;
import com.ams.common.utils.RedisUtils;
import com.ams.common.utils.SnConstant;
import com.ams.enums.*;
import com.ams.model.*;
import com.ams.service.*;
import com.ams.service.impl.WcsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class PalSetHandler implements IBaiyHandler {

    @Autowired
    EntrancePrivilegeService entrancePrivilegeService;

    @Autowired
    DocAsnDetailsService docAsnDetailsService;

    @Autowired
    DocAsnHeaderService docAsnHeaderService;

    @Autowired
    DocOrderDetailsService docOrderDetailsService;

    @Autowired
    DocOrderHeaderService docOrderHeaderService;

    @Autowired
    BasLocationService basLocationService;

    @Autowired
    InvLotLocIdService invLotLocIdService;

    @Autowired
    WcsService wcsService;

    @Autowired
    RedisUtils redisUtils;

    @Override
    public boolean handle(List<Object> dataArr) {
        log.info("【PalSetHandler handle】start >>>>>>>>>>>>>>>>");
        EntrancePrivilege entrancePrivilegeQuery = new EntrancePrivilege();
        entrancePrivilegeQuery.setEntrancestatus(EntranceStatus.ENTER.getMessage());
        EntrancePrivilege entrancePrivilege = entrancePrivilegeService.findFirstByModel(entrancePrivilegeQuery);
        if (entrancePrivilege == null) {
            return false;
        }
        log.info("【PalSetHandler handle】EntrancePrivilege enter >>>>>>>>>>>>>>>>");
        String orderno = entrancePrivilege.getOrderno();
        String rackId = (String)dataArr.get(1);
        String locationId = (String)dataArr.get(2);
        Integer status = (Integer)dataArr.get(3);
        Integer curStock = (Integer)dataArr.get(4);
        log.info("【PalQtyHandler handle】rackId = {} locationId = {} status = {} curStock ={}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", rackId, locationId, status, curStock);
        String matno = basLocationService.getMatnoByRackIdAndLotId(rackId, locationId);
        String nextMatno = null;
        if (status == 0x100) {// 入库
            log.info("【PalSetHandler handle】入库 >>>>>>>>>>>>>>>>");
            DocAsnDetails docAsnDetails = new DocAsnDetails();
            docAsnDetails.setSku(matno);
            docAsnDetails.setAsnno(orderno);

            DocAsnDetails curDetail = docAsnDetailsService.findFirstByModel(docAsnDetails);
            if(curDetail == null) {
                return false;
            }
            if (curDetail.getReceivedqty().compareTo(curDetail.getExpectedqty()) != 0 ) {
                log.info("【PalSetHandler asn】mat = {} 没有达到数量预期不能完成 rece = {} expec = {}>>>>>>>>>>>>>>>>", matno, curDetail.getReceivedqty(), curDetail.getExpectedqty());
                return false;
            }
            docAsnDetails.setLinestatus(OrderDetailStatusEnum.FINISHED.getMessage());
            docAsnDetailsService.updateStatusBySkuModel(docAsnDetails);

            // 更新库存
            syncStock(rackId, locationId, curStock, matno, docAsnDetails.getLotatt04(), BigDecimal.ZERO);

            DocAsnDetails docAsnDetailsQuery = new DocAsnDetails();
            docAsnDetailsQuery.setAsnno(orderno);
            docAsnDetailsQuery.setLinestatus(OrderDetailStatusEnum.OPERATION.getMessage());
            DocAsnDetails nextDocAsnDetails = docAsnDetailsService.findFirstByModel(docAsnDetailsQuery);
            if (nextDocAsnDetails != null) {
                nextMatno = nextDocAsnDetails.getSku();
            }


        } else if (status == 0x200) {
            log.info("【PalSetHandler handle】出库 >>>>>>>>>>>>>>>>");
            DocOrderDetails docOrderDetails = new DocOrderDetails();
            docOrderDetails.setSku(matno);
            docOrderDetails.setOrderno(orderno);

            DocOrderDetails curDetail = docOrderDetailsService.findFirstByModel(docOrderDetails);
            if(curDetail == null) {
                return false;
            }
            if (curDetail.getQtyshipped().compareTo(curDetail.getQtyordered()) != 0) {
                log.info("【PalSetHandler order】mat = {} 没有达到数量预期不能完成 ordered = {} shipped = {}>>>>>>>>>>>>>>>>", matno, curDetail.getQtyordered(), curDetail.getQtyshipped());
                return false;
            }

            DocOrderDetails curOrderDetails =  docOrderDetailsService.findFirstByModel(docOrderDetails);
            BigDecimal curShippedStock = curOrderDetails.getQtyshipped();
            docOrderDetails.setLinestatus(OrderDetailStatusEnum.FINISHED.getMessage());
            docOrderDetailsService.updateStatusBySkuModel(docOrderDetails);

            // 更新库存
            syncStock(rackId, locationId, curStock, matno, docOrderDetails.getLotatt04(), curShippedStock);


            DocOrderDetails docOrderDetailsQuery = new DocOrderDetails();
            docOrderDetailsQuery.setOrderno(orderno);
            docOrderDetailsQuery.setLinestatus(OrderDetailStatusEnum.OPERATION.getMessage());
            DocOrderDetails nextDocOrderDetails = docOrderDetailsService.findFirstByModel(docOrderDetailsQuery);
            if (nextDocOrderDetails != null) {
                nextMatno = nextDocOrderDetails.getSku();
            }
        }

        String curTrayId = redisUtils.get(RedisKeys.LINK_TRAY_ID);

        // 全部完成了
        if(nextMatno == null) {
            log.info("【PalSetHandler handle】全部完成了 >>>>>>>>>>>>>>>>");
            // 控制灯显示
            try {
                wcsService.lightOperation(LightOperationStatus.ALL_FINISH);
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 退回托盘
            wcsService.linkOperation(curTrayId, LinkOperationStatus.RETURN.getCode());
            log.info("【PalSetHandler handle】退回托盘 >>>>>>>>>>>>>>>>");
            // 修改结单状态
            if (orderno.indexOf(SnConstant.DOC_ASN_PREFIX) > -1) {
                DocAsnHeader docAsnHeader = new DocAsnHeader();
                docAsnHeader.setAsnno(orderno);
                docAsnHeader.setAsnstatus(OrderStatusEnum.FINISHED.getMessage());
                docAsnHeaderService.update(docAsnHeader);

                log.info("【PalSetHandler handle】修改结单状态完成 >>>>>>>>>>>>>>>>");
                entrancePrivilegeService.upadteStatusByStastus(EntranceStatus.ENTER.getMessage(), EntranceStatus.FINISH.getMessage());

                log.info("【WDS 通知完成 asn】 >>>>>>>>>>>>>>>>>>>>>>>>>");
                // 通知WDS
                try {
                    docAsnHeader = docAsnHeaderService.findById(orderno);
                    DataInsEntity dataInsEntity = new DataInsEntity();
                    InsEntity insEntity = new InsEntity();
                    insEntity.setSuccess("0");
                    insEntity.setTaskno(docAsnHeader.getAsnreference1());
                    insEntity.setTaskLevel(Integer.parseInt(docAsnHeader.getPriority()));
                    insEntity.setTaskTime(docAsnHeader.getPriority());
                    insEntity.setMessage("");
                    insEntity.setTaskSource(docAsnHeader.getHEdi04());
                    List<InsEntity> insEntityList = new ArrayList<>();
                    DocAsnDetails docAsnDetails = new DocAsnDetails();
                    docAsnDetails.setAsnno(docAsnHeader.getAsnno());
                    List<DocAsnDetails> docAsnDetailsList = docAsnDetailsService.findByModel(docAsnDetails);
                    List<InsDetailEntity> insDetailEntityList = new ArrayList<>();
                    for (DocAsnDetails asnDetails : docAsnDetailsList) {
                        InsDetailEntity insDetailEntity = new InsDetailEntity();
                        insDetailEntity.setBatch(asnDetails.getLotatt04());
                        insDetailEntity.setMatno(asnDetails.getSku());
                        insDetailEntity.setQuantity(asnDetails.getExpectedqty().floatValue());
                        insDetailEntity.setUnit(asnDetails.getUom());
                        insDetailEntity.setMatText(asnDetails.getAlternativesku());
                        insDetailEntityList.add(insDetailEntity);
                    }
                    insEntity.setReserve(insDetailEntityList);
                    insEntityList.add(insEntity);
                    dataInsEntity.setData(insEntityList);
                    String finishJson = JSONObject.toJSONString(dataInsEntity);
                    wcsService.asyncFinishWms1TaskJson(finishJson);

                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("【WDS 通知失败 asn", e);
                }

            }else if(orderno.indexOf(SnConstant.DOC_ORDER_PREFIX) > -1){
                DocOrderHeader docOrderHeader = new DocOrderHeader();
                docOrderHeader.setOrderno(orderno);
                docOrderHeader.setSostatus(OrderStatusEnum.FINISHED.getMessage());
                docOrderHeaderService.update(docOrderHeader);
                log.info("【PalSetHandler handle】修改结单状态完成 >>>>>>>>>>>>>>>>");
                entrancePrivilegeService.upadteStatusByStastus(EntranceStatus.ENTER.getMessage(), EntranceStatus.FINISH.getMessage());

                log.info("【WDS 通知完成 order】 >>>>>>>>>>>>>>>>>>>>>>>>>");

                // 通知WDS
                try {
                    docOrderHeader = docOrderHeaderService.findById(orderno);
                    DataInsEntity dataInsEntity = new DataInsEntity();
                    InsEntity insEntity = new InsEntity();
                    insEntity.setSuccess("0");
                    insEntity.setTaskno(docOrderHeader.getSoreference1());
                    insEntity.setTaskLevel(Integer.parseInt(docOrderHeader.getPriority()));
                    insEntity.setTaskTime(docOrderHeader.getPriority());
                    insEntity.setMessage("");
                    insEntity.setTaskSource(docOrderHeader.getHEdi04());
                    List<InsEntity> insEntityList = new ArrayList<>();
                    DocAsnDetails docAsnDetails = new DocAsnDetails();
                    docAsnDetails.setAsnno(docOrderHeader.getOrderno());
                    List<DocAsnDetails> docAsnDetailsList = docAsnDetailsService.findByModel(docAsnDetails);
                    List<InsDetailEntity> insDetailEntityList = new ArrayList<>();
                    for (DocAsnDetails asnDetails : docAsnDetailsList) {
                        InsDetailEntity insDetailEntity = new InsDetailEntity();
                        insDetailEntity.setBatch(asnDetails.getLotatt04());
                        insDetailEntity.setMatno(asnDetails.getSku());
                        insDetailEntity.setQuantity(asnDetails.getExpectedqty().floatValue());
                        insDetailEntity.setUnit(asnDetails.getUom());
                        insDetailEntity.setMatText(asnDetails.getAlternativesku());
                        insDetailEntityList.add(insDetailEntity);
                    }
                    insEntity.setReserve(insDetailEntityList);
                    insEntityList.add(insEntity);
                    dataInsEntity.setData(insEntityList);
                    String finishJson = JSONObject.toJSONString(dataInsEntity);
                    wcsService.asyncFinishWms1TaskJson(finishJson);
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("【WDS 通知失败 order】", e);
                }

            }
        } else {
            String trayId = basLocationService.getTrayIdBySku(nextMatno);
            // 不换托盘
            if (curTrayId.equals(trayId)) {
                log.info("【PalSetHandler handle】部分完成 不换托盘 nextMatno = {} >>>>>>>>>>>>>>>>", nextMatno);
                // 控制灯显示
                try {
                    wcsService.lightOperation(LightOperationStatus.PART_FINISH);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else{
                log.info("【PalSetHandler handle】部分完成 换托盘 nextMatno = {} >>>>>>>>>>>>>>>>", nextMatno);
                // 控制灯显示
                try {
                    wcsService.lightOperation(LightOperationStatus.CHANGE);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 换托盘
                wcsService.linkOperation(curTrayId, LinkOperationStatus.RETURN.getCode());
                log.info("【PalSetHandler handle】部分完成 退托盘 curTrayId = {} >>>>>>>>>>>>>>>>", curTrayId);
                wcsService.linkOperation(trayId, LinkOperationStatus.CALL.getCode());
                log.info("【PalSetHandler handle】部分完成 吐托盘 trayId = {} >>>>>>>>>>>>>>>>", trayId);
            }
        }

        return true;
    }

    private boolean syncStock(String rackId, String locationId, Integer curStock, String matno, String batchNum,BigDecimal shippedStock) {
        InvLotLocId invLotLocId = invLotLocIdService.findById(rackId, locationId);

        if(invLotLocId!=null) {
            // 更新库存
            invLotLocId.setQtyallocated(invLotLocId.getQtyallocated().subtract(shippedStock));
            invLotLocId.setQty(BigDecimal.valueOf(curStock));
            if(shippedStock.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal clearAfterStock = invLotLocId.getQtyallocated().subtract(shippedStock);
                if (clearAfterStock.compareTo(BigDecimal.ZERO) > 0) {
                    invLotLocId.setQtyallocated(clearAfterStock);
                }
            }
            return invLotLocIdService.update(invLotLocId);
        } else {
            invLotLocId = new InvLotLocId();
            invLotLocId.setLocationid(locationId);
            invLotLocId.setRackid(rackId);
            invLotLocId.setSku(matno);
            invLotLocId.setCustomerid("WRC");
            invLotLocId.setLotnum(batchNum);
            invLotLocId.setQtyallocated(BigDecimal.ZERO);
            invLotLocId.setQty(BigDecimal.valueOf(curStock));
            return invLotLocIdService.insert(invLotLocId) != null;
        }
    }

}
